package com.ym.medical.service.impl;

import cn.hutool.core.exceptions.ExceptionUtil;
import com.alibaba.fastjson.JSONObject;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.ym.common.constant.Constants;
import com.ym.common.enums.SmsTemplateEnum;
import com.ym.common.utils.SmsUtil;
import com.ym.core.utils.DateKit;
import com.ym.core.utils.tkmybatis.TK;
import com.ym.core.utils.yunxin.YunXunApiUtil;
import com.ym.medical.dao.CouponReceiveRecordDao;
import com.ym.medical.dao.DoctorPhoneSettingDao;
import com.ym.medical.dao.DoctorServicePriceDao;
import com.ym.medical.domain.bo.pay.WxOrderQueryRespData;
import com.ym.medical.domain.bo.pay.WxRefundQueryRespData;
import com.ym.medical.domain.entity.*;
import com.ym.medical.domain.vo.HuaWeiPhoneRecordVo;
import com.ym.medical.domain.vo.InquiryOrderVo;
import com.ym.medical.domain.vo.MindListMobileVO;
import com.ym.medical.domain.vo.PhoneInfoVo;
import com.ym.medical.enums.*;
import com.ym.medical.service.*;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.text.SimpleDateFormat;
import java.util.*;

/**
 * @author: 张文博
 * @version: 2019年06月14日 14:27
 */
@Service
public class TimedTaskImpl implements ITimedTaskSV {

    private static final Logger logger = LoggerFactory.getLogger(TimedTaskImpl.class);

    @Autowired
    private DoctorServicePriceDao doctorServicePriceDao;

    @Autowired
    private IInquiryOrderSV iInquiryOrderSV;

    @Autowired
    private DoctorPhoneSettingDao doctorPhoneSettingDao;

//	@Autowired
//	private DoctorTextSettingDao doctorTextSettingDao;

    @Autowired
    private IDoctorSV iDoctorSV;

    @Autowired
    private IHuaweiReturnParamSV iHuaweiReturnParamSV;

    @Autowired
    private IAxbResultSV iAxbResultSV;

    @Autowired
    private IInformationSV iInformationSV;

    @Autowired
    private WxPaySVImpl wxPayApplySV;

    @Autowired
    private IOrderPaySV orderPaySV;

    @Autowired
    private CouponReceiveRecordDao receiveRecordDao;

    @Autowired
    private IDoctorServiceItemSV iDoctorServiceItemSV;

    @Autowired
    private IPayExceptionRecordSV payExceptionRecordSV;

    @Autowired
    private IVerifyExcpBillSV verifyExcpBillSV;

    @Autowired
    private INormalTradeBillSV normalTradeBillSV;

    @Autowired
    private IMindSV mindSV;

    @Autowired
    private IPersonalTransactionOrderSV personalTransactionOrderSV;

    @Autowired
    private ISysCodeRuleSV sysCodeRuleSV;


    /***
     * 医生患者电话服务
     */
    @Override
    public void call() throws InterruptedException {
        /*
         *查询订单中电话预约列表
         * 患者电话 医生电话 通话时长
         */

        //List<PhoneInfoVo> phoneInfoVos = inquiryOrderDao.selectPhoneInfo();
        List<PhoneInfoVo> list = new ArrayList<>();
        PhoneInfoVo vv = new PhoneInfoVo();
        vv.setPhoneNo("18729871364");
        vv.setDoctPhone("17688939197");
        vv.setPrDuration(60);
        list.add(vv);
        PhoneInfoVo vv2 = new PhoneInfoVo();
        vv2.setPhoneNo("15339246106");
        vv2.setDoctPhone("15594980703");
        vv2.setPrDuration(60);
        list.add(vv2);

        for (PhoneInfoVo vo : list) {
            Map<String, String> map = YunXunApiUtil.createAuthorizationAndSignUrl();
            String url = map.get("url");
            String authorization = map.get("authorization");
            Map<String, Object> parames = new HashMap<>();
            parames.put("action", YunXunApiUtil.ACTION);
            parames.put("appid", YunXunApiUtil.APPID);
            parames.put("srcclid", YunXunApiUtil.SRCCLID);
            parames.put("dstclid", YunXunApiUtil.DSTCLID);
            parames.put("src", vo.getDoctPhone());//	第一端号码
            parames.put("dst", vo.getPhoneNo());//第二端号码
            parames.put("credit", vo.getPrDuration());//时长
            parames.put("customParm", vo.getIoNum());//标识与订单关联
//            String json = HttpUtil.post(url)
//                    .header("Content-Type", "application/json;charset=utf-8")
//                    .header("Authorization",authorization)
//                    .header("Accep", "application/json")
//                    .body(parames).execute();
            ObjectMapper mapper = new ObjectMapper();
//        AA aa = mapper.readValue(json,AA.class);
//        System.out.println(aa);
            //System.out.println(json);
            Thread.sleep(10000);
        }

    }

    /***
     * 医生电话规则单价定时任务失效任务
     */
    @Override
    public void updateToInvalidState() {

        //失效时间比当前(getValidTime())时间小生效  2019-05-21 23:59:51
        doctorServicePriceDao.updateToInvalidState(iDoctorServiceItemSV.getValidTime());

    }

    @Override
    public void updateToValidState() {
        //生效时间比当前时间小失效  2019-05-21 23:59:55
        doctorServicePriceDao.updateToValidState(iDoctorServiceItemSV.getValidTime());
    }


    /**
     * 凌晨修改不可预约时间可预约
     */
    @Override
    public void updateNotFlagTrue() {
        doctorPhoneSettingDao.updateNotFlagTrue();

    }

//	/**
//	 * 图文设置生效失效任务
//	 */
//	@Override
//	public void updateTextSet() {
//		Date date = new Date();
//		//失效时间比当前时间小生效  2019-05-21 23:59:51
//		doctorTextSettingDao.updateInvalidState(date);
//		//生效时间比当前时间小失效  2019-05-21 23:59:55
//		doctorTextSettingDao.updateValidState(date);
//
//	}

    /**
     * 电话录音文件下载上传
     */
    @Override
    public void downAndUp(Long ioId) {
        try {
            //查询已拨电话录音文件信息
            List<HuaWeiPhoneRecordVo> recordVo = iHuaweiReturnParamSV.recordInfo(ioId);
            if (recordVo.isEmpty()) {
                return;
            }
            for (HuaWeiPhoneRecordVo phoneRecordVo : recordVo) {
                String uid = iDoctorSV.axbGetRecordDownloadLink(
                        phoneRecordVo.getRecordDomain(), phoneRecordVo.getRecordObjectName(), phoneRecordVo.getPatientId());
                AxbResultEntity axbResult = new AxbResultEntity();
                AxbResultEntity axbResult1 = iAxbResultSV.selectById(phoneRecordVo.getId());
                if (axbResult1.getFileInfoId() != null && !"".equals(axbResult1.getFileInfoId())) {
                    axbResult.setFileInfoId(axbResult1.getFileInfoId() + "," + uid);
                } else {
                    axbResult.setFileInfoId(uid);
                }
                axbResult.setUpTime(new Date());
                axbResult.setId(phoneRecordVo.getId());
                iAxbResultSV.updateById(axbResult);
            }
        } catch (Exception e) {
            logger.error(ExceptionUtil.getMessage(e));
        }
    }

    /**
     * 医生打电话前5分钟发送消息  注意接听电话通知
     */
    @Override
    public void sendAnswerNotice() {
        //查询表中接近打电话的订单
        List<InquiryOrderVo> orders = iInquiryOrderSV.beforeFiveMinutesOrder();
        if (orders.isEmpty()) {
            return;
        }
        Map<String, Object> map = null;
        JSONObject jsonObject = null;
        SimpleDateFormat format = new SimpleDateFormat(DateKit.YYYYMMDD);
        for (InquiryOrderVo order : orders) {
			/*Date time = order.getAppointTime();
			String newTime = format.format(time);
			String newPrice = String.valueOf(order.getPaymentPrice());
			map = new HashMap<>(8);
			map.put("ioNum", order.getIoNum());
			map.put("patientName", order.getPName());
			map.put("doctorName", order.getDoctorName());
			map.put("illnessDesc", order.getIllnessDesc());
			map.put("appointTime", newTime);
			map.put("matter", "请注意接听电话 接听电话为:"+ order.getPhoneNo());
			map.put("paymentPrice", newPrice);*/
            //患者短信
            SmsUtil.sendSms(order.getPhoneNo(), SmsTemplateEnum.INQUIRY_TELEPHONE_START_SHORT_MESSAGE_REMINDER,
                    order.getDoctorName(), "电话问诊", "17118562482");
            //医生短信
            SmsUtil.sendSms(order.getPhoneNo(), SmsTemplateEnum.DOCTOR_S_TELEPHONE_CONSULTATION_IS_ABOUT_TO_START,
                    order.getDoctorName(), order.getPName());

            iInformationSV.generatePhoneInquiryInformation(
                    order.getDoctorId(), order.getUserId(),
                    Constants.InquiryAdvice.PHONE,
                    order.getIllnessDesc(), order.getFileInforId(), order.getId());

        }


    }

//	@Override
//	public void deleteInvalidFormId() {
//		WxPayApplyModel model = new WxPayApplyModel();
//		model.setQueryByWhereClause("where create_time < '" + DateKit.getBeforeTime(new Date(), 0, 0, -1, 0, 0, 0, DateKit.YYYY_MM_DD_HH_MM_SS) + "'");
//		wxPayApplySV.deleteByModel(model);
//	}

    @Override
    public void updateOrderPayState() throws Exception {
        //问诊订单
        String[] payStates = {InquiryOrderPaymentStateEnum.TO_BE_PAID.getKey(), InquiryOrderPaymentStateEnum.REFUND_APPLYING.getKey()};
        List<InquiryOrderEntity> inquiryOrders = iInquiryOrderSV.selectList(
                TK.select(InquiryOrderEntity.class)
                        .where()
                        .andIn(InquiryOrderEntity::getPaymentState, payStates)
                        .andEqualTo(InquiryOrderEntity::getPaymentWay, PaymentWayEnum.WECHAT.getKey())
                        .end()
        );

        for (InquiryOrderEntity order : inquiryOrders) {
            InquiryOrderPaymentStateEnum enumByCode = InquiryOrderPaymentStateEnum.valueOf(order.getPaymentState());
            switch (enumByCode) {
                case TO_BE_PAID:
                    //更新微信支付订单
                    orderPaySV.wxPayOrder(order);
                    break;
                case REFUND_APPLYING:
                    //更新微信退费订单
                    orderPaySV.wxrefundOrder(order);
                    break;
                default:
                    break;
            }
        }

        //送心意订单
        List<MindEntity> mindEntities = mindSV.selectList(
                TK.select(MindEntity.class)
                        .where()
                        .andEqualTo(MindEntity::getPayState, PaymentStateEnum.TO_BE_PAID.getKey())
                        .andEqualTo(MindEntity::getPayType, PaymentWayEnum.WECHAT.getKey())
                        .end()
        );

        for (MindEntity mind : mindEntities) {
            orderPaySV.mindOrder(mind.getIoNum());
        }


        //充值体现订单
        List<PersonalTransactionOrderEntity> transactionOrderEntities = personalTransactionOrderSV.selectList(
                TK.select(PersonalTransactionOrderEntity.class)
                        .where()
                        .andEqualTo(PersonalTransactionOrderEntity::getPayState, PaymentStateEnum.TO_BE_PAID.getKey())
                        .andEqualTo(PersonalTransactionOrderEntity::getDfAccType, PaymentWayEnum.WECHAT.getKey())
                        .end()
        );

        for (PersonalTransactionOrderEntity personalTransactionOrder : transactionOrderEntities) {
            if (personalTransactionOrder.getAccId() == null) {
                continue;
            }
            orderPaySV.withdrawCallBack(personalTransactionOrder.getIoNum());
        }
    }

    /**
     * 优惠券失效任务
     */
    @Override
    public void updateCouponUseState() {
        receiveRecordDao.updateCouponUseState();

    }

    /**
     * 1、平台有，微信没有，则调用微信查询订单状态接口，如果有则， 刷新为：已处理，已对账，并将该订单复制到正常账单中；
     * 如果没有，则刷新为：已处理，异常类型改为：03
     * 2、微信有，平台没有，则补调微信回调业务逻辑,并将该订单复制到正常账单中；
     */
    @Override
    public void handleWxBillExcep() throws Exception {
        //1. 获取所有未处理的微信对账异常记录
        String[] execTypes = {BillExecTypeEnum.PAYER_NOT_EXIST.getKey(), BillExecTypeEnum.PLATFORM_NOT_EXIST.getKey()};
        List<VerifyExcpBillEntity> verifyExcpBillEntities = verifyExcpBillSV.selectList(
                TK.select(VerifyExcpBillEntity.class)
                        .where()
                        .andEqualTo(VerifyExcpBillEntity::getHandleStatus, ExecBillHandleStatusEnum.UNTREATED.getKey())
                        .andIn(VerifyExcpBillEntity::getExecType, execTypes)
                        .end()
        );

        for (VerifyExcpBillEntity verifyExcpBill : verifyExcpBillEntities) {
            //2. 按照异常类型进行相应的处理
            BillExecTypeEnum enumByCode = BillExecTypeEnum.valueOf(verifyExcpBill.getExecType());
            //判断支付方式
            PaymentWayEnum payType = PaymentWayEnum.valueOf(verifyExcpBill.getPayType());
            //业务类型
            BillBusTypeEnum busTypeEnum = BillBusTypeEnum.valueOf(verifyExcpBill.getBusType());
            String outTradeNo = verifyExcpBill.getOutTradeNo();

            //--------------------------------------------订单类型校验 ---------------------------------------------------------------
            String ruleCode = sysCodeRuleSV.selectByIoNum(outTradeNo);        //根据订单号查询规则编号
            String inquiryCode = CodeRuleEnum.VISIT_ORDER.getCode();   //就诊订单
            String sxyCode = CodeRuleEnum.SXY_ORDER.getCode();        //送心意订单
            String rwCode = CodeRuleEnum.RECHARGE_WITHDRAW_ORDER.getCode();    //充值提现订单
            InquiryOrderEntity inquiryOrder = null;  // 目前只有问诊订单才存在退费
            MindListMobileVO mindModel = null;   //送心意订单
            PersonalTransactionOrderEntity personalTransactionOrder = null;  //充值提现订单
            String payState = null;
            if (inquiryCode.equals(ruleCode)) {
                inquiryOrder = iInquiryOrderSV.selectByIoNum(verifyExcpBill.getOutTradeNo());
                if (inquiryOrder == null) {
                    logger.info("该问诊订单不存在,订单号:{}", outTradeNo);
                    continue;
                }
                payState = inquiryOrder.getPaymentState();
            } else if (sxyCode.equals(ruleCode)) {
                mindModel = mindSV.getMindModelByIoNum(outTradeNo);
                if (mindModel == null) {
                    logger.info("该送心意订单不存在,订单号:{}", outTradeNo);
                    continue;
                }
                payState = mindModel.getPayState();
            } else if (rwCode.equals(ruleCode)) {
                personalTransactionOrder = personalTransactionOrderSV.selectByIoNum(outTradeNo);
                if (personalTransactionOrder == null) {
                    logger.info("该充值提现订单不存在,订单号:{}", outTradeNo);
                    continue;
                }
                payState = personalTransactionOrder.getPayState();
            }
            //--------------------------------------------订单类型校验 ---------------------------------------------------------------

            switch (payType) {
                case WECHAT:   //微信
                    switch (enumByCode) {
                        case PAYER_NOT_EXIST:   //平台存在，支付方不存在
                            WxOrderQueryRespData orderQueryRespData;
                            WxRefundQueryRespData refundQueryRespData;
                            switch (busTypeEnum) {
                                case PAY:
                                    ConsumeDetailsTdTypeEnum consumeDetailsTdTypeEnum = null;
                                    if (inquiryCode.equals(ruleCode)) {
                                        consumeDetailsTdTypeEnum =  ConsumeDetailsTdTypeEnum.valueOf(inquiryOrder.getIoType());
                                    } else if (sxyCode.equals(ruleCode)) {
                                        consumeDetailsTdTypeEnum = ConsumeDetailsTdTypeEnum.TO_MIND;
                                    } else if (rwCode.equals(ruleCode)) {
                                        consumeDetailsTdTypeEnum = ConsumeDetailsTdTypeEnum.RECHARGE;
                                    }
                                    orderQueryRespData = orderPaySV.orderPayQuery(verifyExcpBill.getOutTradeNo(), consumeDetailsTdTypeEnum);
                                    if (orderQueryRespData != null) {
                                        processWxPayNotExist(verifyExcpBill, orderQueryRespData);
                                    }
                                    break;
                                case REFUND:
                                    refundQueryRespData = orderPaySV.refundOrderQuery(verifyExcpBill.getOutTradeNo());
                                    if (refundQueryRespData != null) {
                                        processWxRefundNotExist(verifyExcpBill, refundQueryRespData);
                                    }
                                    break;
                            }

                            break;
                        case PLATFORM_NOT_EXIST:  //支付方存在，平台不存在
                            //1.执行微信业务回调业务
                            switch (busTypeEnum) {
                                case PAY:
                                    if ("01".equals(payState)) {
                                        if (inquiryCode.equals(ruleCode)) {
                                            orderPaySV.updateOrderInfo(inquiryOrder, verifyExcpBill.getTradeNo());
                                        } else if (sxyCode.equals(ruleCode)) {
                                            orderPaySV.updateMindOrder(mindModel, verifyExcpBill.getTradeNo());
                                        } else if (rwCode.equals(ruleCode)) {
                                            orderPaySV.updateRechargeOrder(personalTransactionOrder, verifyExcpBill.getTradeNo());
                                        }
                                    }
                                    break;
                                case REFUND:
                                    if ("03".equals(payState)) {
                                        inquiryOrder.setPaymentTime(verifyExcpBill.getTradeTime());
                                        orderPaySV.wxrefundUpdateOrderInfo(inquiryOrder, verifyExcpBill.getTradeNo());
                                    }
                                    break;
                            }

                            //2.将订单复制到正常订单中
                            NormalTradeBillEntity normalTradeBill = new NormalTradeBillEntity();
                            BeanUtils.copyProperties(verifyExcpBill, normalTradeBill);
                            normalTradeBill.setCreateTime(new Date());
                            normalTradeBillSV.insert(normalTradeBill);
                            break;
                        default:           // 支付方属实不存在，系统异常normal_trade_bill
                            break;
                    }
                    break;
                default:
                    //后续扩展
                    break;
            }
        }

    }

    private void processWxPayNotExist(VerifyExcpBillEntity verifyExcpBill, WxOrderQueryRespData result) {
        String tradeState = result.getTradeState();
        if ("SUCCESS".equals(tradeState)) {
            logger.info("----------------------------------------查询订单接口业务成功 /orderQuery url:{}---------------------------------------------------", result);
            //1.刷新异常订单状态 已处理，已对账
            verifyExcpBill.setHandleStatus(ExecBillHandleStatusEnum.HAVE_TO_DEAL_WITH.getKey());
            verifyExcpBill.setBillStatus(BillStatusEnum.HAVE_CHECK.getKey());
            verifyExcpBillSV.updateById(verifyExcpBill);
            //2.将订单复制到正常订单中
            NormalTradeBillEntity normalTradeBill = new NormalTradeBillEntity();
            BeanUtils.copyProperties(verifyExcpBill, normalTradeBill);
            normalTradeBill.setCreateTime(new Date());
            normalTradeBillSV.insert(normalTradeBill);
        } else {
            //刷新异常订单状态 已处理，支付方属实不存在，系统异常normal_trade_bill
            verifyExcpBill.setHandleStatus(ExecBillHandleStatusEnum.HAVE_TO_DEAL_WITH.getKey());
            verifyExcpBill.setExecType(BillExecTypeEnum.SYSTEM_EXCEPTION.getKey());
            verifyExcpBillSV.updateById(verifyExcpBill);
        }
    }

    private void processWxRefundNotExist(VerifyExcpBillEntity verifyExcpBill, WxRefundQueryRespData result) {
        List<String> refundStatusList = result.getRefundStatusList();

        String refundStatus = refundStatusList.get(0);
        if (!refundStatusList.isEmpty()) {
            if (WxRefundStateEnum.PROCESSING.getKey().equals(refundStatus)) {
                return;
            }
            if (WxRefundStateEnum.SUCCESS.getKey().equals(refundStatus)) {
                logger.info("----------------------------------------查询订单接口业务成功 /refundQuery url:{}---------------------------------------------------", result);
                //1.刷新异常订单状态 已处理，已对账
                verifyExcpBill.setHandleStatus(ExecBillHandleStatusEnum.HAVE_TO_DEAL_WITH.getKey());
                verifyExcpBill.setBillStatus(BillStatusEnum.HAVE_CHECK.getKey());
                verifyExcpBillSV.updateById(verifyExcpBill);
                //2.将订单复制到正常订单中
                NormalTradeBillEntity normalTradeBill = new NormalTradeBillEntity();
                BeanUtils.copyProperties(verifyExcpBill, normalTradeBill);
                normalTradeBill.setCreateTime(new Date());
                normalTradeBillSV.insert(normalTradeBill);
            } else {
                verifyExcpBill.setHandleStatus(ExecBillHandleStatusEnum.HAVE_TO_DEAL_WITH.getKey());
                verifyExcpBill.setExecType(BillExecTypeEnum.SYSTEM_EXCEPTION.getKey());
                verifyExcpBillSV.updateById(verifyExcpBill);
            }
        }
        logger.info("----------------------------------------退款回调接口业务成功 /orderRefundCallback url:{}---------------------------------------------------", result);
    }
}
